/**
 * 
 * 
 */
namespace Validation{
  export interface StringValidator{
    isAcceptable(s:string):boolean;
  }
  const letterRegexp = /^[A-Za-z]+$/;
  const numberRegxp = /^[0-9]+$/;

  export class LettersOnlyValidator implements StringValidator{
    isAcceptable(s: string): boolean {
        return letterRegexp.test(s);
    }
  }

  export class ZipCodeValidator implements StringValidator{
    isAcceptable(s: string): boolean {
        return s.length === 5 && numberRegxp.test(s);
    }
  }
}
namespace Validation2{
  export interface StringValidator{
    isAcceptable(s:string):boolean;
  }  
}
let strings = ["hello","7816","101"];
let validators: {[s:string]:Validation.StringValidator;} = {};
validators["zip code"] = new Validation.ZipCodeValidator();
validators["letters only"] = new Validation.LettersOnlyValidator();

for(let s of strings){
  for(let name in validators){
    console.log(`"${s}" - ${validators[name].isAcceptable(s)? "matches": "does not match"} ${name}`)
  } 
}


/***分离到多文件
当应用变得越来越大时，我们需要将代码分离到不同的文件中以便于维护。

多文件中的命名空间
现在，我们把Validation命名空间分割成多个文件。 尽管是不同的文件，它们仍是同一个命名空间，并且在使用的时候就如同它们在一个文件中定义的一样。 因为不同文件之间存在依赖关系，所以我们加入了引用标签来告诉编译器文件之间的关联。 我们的测试代码保持不变。 */
namespace Validation {
  export interface StringValidator {
      isAcceptable(s: string): boolean;
  }
}


/**外部命名空间
流行的程序库D3在全局对象d3里定义它的功能。 因为这个库通过一个 <script>标签加载（不是通过模块加载器），它的声明文件使用内部模块来定义它的类型。 为了让TypeScript编译器识别它的类型，我们使用外部命名空间声明。 比如，我们可以像下面这样写： */
declare namespace D3 {
  export interface Selectors {
      select: {
          (selector: string): Selection;
          (element: EventTarget): Selection;
      };
  }

  export interface Event {
      x: number;
      y: number;
  }

  export interface Base extends Selectors {
      event: Event;
  }
}

declare var d3: D3.Base;